home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection 1998 Fall: Game Toolkit / Disc.iso / SDKs / PCI Driver Development Kit / • Tools / Utility / LogLibrary 950622 / Src / MathLib64.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-20  |  5.6 KB  |  188 lines  |  [TEXT/MPCC]

  1. /*                                        MathLib64.c                                    */
  2. /*
  3.  * Add64.c
  4.  * Copyright © 1995 Apple Computer Inc. All Rights Reserved.
  5.  *
  6.  *        Add64(&aWideValue, &bWideValue, &result)        result = a + b
  7.  *        Subtract64(&aWideValue, &bWideValue, &result)    result = a - b
  8.  *        Multiply64(&aWideValue, &longValue, &result)    result = a * b
  9.  *        Divide64(&aWideValue, &bWideValue, &result)        result = a / b;
  10.  *                                                        a = a mod b (remainder)
  11.  *
  12.  * The multiply and divide routines were adapted from "A Guide to Illiac Programming"
  13.  * Written by
  14.  *    Martin Minow
  15.  */
  16. #include <Types.h>
  17.  
  18. /*
  19.  * Copy these prototypes to your calling application header file.
  20.  */
  21. void                        Add64(
  22.         register const UnsignedWide    *aPtr,
  23.         register const UnsignedWide    *bPtr,
  24.         register UnsignedWide        *result
  25.     );
  26. void                        Subtract64(
  27.         register const UnsignedWide    *aPtr,
  28.         register const UnsignedWide    *bPtr,
  29.         register UnsignedWide        *result
  30.     );
  31. void                        Multiply64(
  32.         const UnsignedWide        *multiplicand,    /* Multiplier * multiplicand        */
  33.         UInt32                    multiplier,        /* yields result                    */
  34.         UnsignedWide            *resultPtr
  35.     );
  36. void                        Divide64(            /* quotient = dividend / divisor    */
  37.         UnsignedWide            *dividendPtr,    /* Dividend, becomes remainder        */
  38.         const UnsignedWide        *divisorPtr,    /* Divisor, unchanged                */
  39.         UnsignedWide            *quotientPtr    /* Quotient, result                    */
  40.     );
  41.  
  42.  
  43. static const UInt32        kHighBit = 0x80000000L;
  44.  
  45. /*
  46.  * 64-bit addition. Although the parameters are defined as UnsignedWide, they
  47.  * should work correctly for signed wide.
  48.  */
  49. void
  50. Add64(
  51.         register const UnsignedWide    *aPtr,
  52.         register const UnsignedWide    *bPtr,
  53.         register UnsignedWide        *result
  54.     )
  55. {
  56.         result->lo = aPtr->lo + bPtr->lo;
  57.         result->hi = aPtr->hi + bPtr->hi;
  58.         /*
  59.          * Carry from low-word to high-word if the unsigned result->lo is
  60.          * less than the unsigned interpretation of either source value.
  61.          */
  62.         if (((UInt32) result->lo) < ((UInt32) aPtr->lo))
  63.             result->hi++;
  64. }
  65.  
  66. /*
  67.  * Subtract (2nd argument) from (1st argument):
  68.  */
  69. void
  70. Subtract64(
  71.         register const UnsignedWide    *aPtr,
  72.         register const UnsignedWide    *bPtr,
  73.         register UnsignedWide        *result
  74.     )
  75. {
  76.         if (aPtr->lo >= bPtr->lo)
  77.             result->hi = aPtr->hi - bPtr->hi;
  78.         else {
  79.             result->hi = (aPtr->hi - 1) - bPtr->hi;
  80.         }
  81.         result->lo = aPtr->lo - bPtr->lo;
  82. }
  83.  
  84. /*
  85.  * This is a bit-by-bit (i.e., inefficient) multiplication routine that multiplies
  86.  * two unsigned numbers, returning a 64-bit result.
  87.  *
  88.  * Adapted from "A Guide to Illiac Programming" 1961 Edition.
  89.  */
  90. void
  91. Multiply64(
  92.         const UnsignedWide        *multiplicand,    /* Multiplier * multiplicand        */
  93.         UInt32                    multiplier,        /* yields result                    */
  94.         UnsignedWide            *resultPtr
  95.     )
  96. {
  97.         register int            i;
  98.         UnsignedWide            accumulator;    /* accumulator and resultLo form    */
  99.         register UInt32            resultLo;        /* a 96-bit intermediate register    */
  100.  
  101.         resultLo = 0;                            /* Clear the result accumulator        */
  102.         accumulator.hi = accumulator.lo  = 0;    /* Clear more of the result            */
  103.         for (i = 0; i < 32; i++) {
  104.             if ((multiplier & 1) != 0)
  105.                 Add64(multiplicand, &accumulator, &accumulator);
  106.             multiplier >>= 1;                    /* Right shift multiplier            */
  107.             resultLo >>= 1;                        /* 64-bit right shift of result        */
  108.             if ((accumulator.lo & 1) != 0)        /* Carry from mid word?                */
  109.                 resultLo |= kHighBit;            /* Yes, carry into the low word.    */
  110.             accumulator.lo >>= 1;                /* Right-shift mid word                */
  111.             if ((accumulator.hi & 1) != 0)        /* Carry from high to mid?            */
  112.                 accumulator.lo |= kHighBit;        /* Yes.                                */
  113.             accumulator.hi >>= 1;                /* Finish the 64-bit shift            */
  114.         }
  115.         resultPtr->hi = accumulator.lo;
  116.         resultPtr->lo = resultLo;
  117. }
  118.  
  119. /*
  120.  * This is a bit-by-bit (i.e., inefficient) division routine that will handle a
  121.  * 64-bit unsigned divide. The computation results in:
  122.  *         quotient = dividend / divisor, dividend := remainder.
  123.  * Although it looks pretty ugly in C, Risk pipeline optimization should make short
  124.  * work of the algorithm.
  125.  *
  126.  * Adapted from "A Guide to Illiac Programming" 1961 Edition.
  127.  */
  128. void
  129. Divide64(
  130.         UnsignedWide            *dividendPtr,    /* Dividend, becomes remainder        */
  131.         const UnsignedWide        *divisorPtr,    /* Divisor, unchanged                */
  132.         UnsignedWide            *quotientPtr    /* Quotient, result                    */
  133.     )
  134. {
  135.         register int            i;
  136.         UnsignedWide            accumulator[2];
  137.  
  138.         /*
  139.          * Store the dividend in the low-word of a 128 bit accumulator
  140.          */
  141.         accumulator[0].hi = accumulator[0].lo = 0;
  142.         accumulator[1] = *dividendPtr;
  143.         quotientPtr->hi = quotientPtr->lo = 0;
  144.         for (i = 0; i < 64; i++) {
  145.             /*
  146.              * Left-shift the 64-bit quotient to make room for a new bit.
  147.              */
  148.             quotientPtr->hi <<= 1;
  149.             if ((quotientPtr->lo & kHighBit) != 0)
  150.                 quotientPtr->hi |= 1;
  151.             quotientPtr->lo <<= 1;
  152.             /*
  153.              * Left-shift the 128-bit accumulator. The divisor shifts into
  154.              * the high 64 bit word.
  155.              */
  156.             accumulator[0].hi <<= 1;
  157.             if ((accumulator[0].lo & kHighBit) != 0)
  158.                 accumulator[0].hi |= 1;
  159.             accumulator[0].lo <<= 1;
  160.             if ((accumulator[1].hi & kHighBit) != 0)
  161.                 accumulator[0].lo |= 1;
  162.             accumulator[1].hi <<= 1;
  163.             if ((accumulator[1].lo & kHighBit) != 0)
  164.                 accumulator[1].hi |= 1;
  165.             accumulator[1].lo <<= 1;
  166.             /*
  167.              * Compare the high-word of the accumulator to the divisor.
  168.              */
  169.             if (accumulator[0].hi > divisorPtr->hi
  170.              || (accumulator[0].hi == divisorPtr->hi
  171.               && accumulator[0].lo >= divisorPtr->lo)) {
  172.                 /*
  173.                  * Accumulator is >= divisor, put a bit into the quotient
  174.                  * (remember, we left-shifted it first) and subtract the
  175.                  * divisor from the accumulator high word
  176.                  */
  177.                 quotientPtr->lo |= 1;
  178.                 if (accumulator[0].lo >= divisorPtr->lo)
  179.                     accumulator[0].hi -= divisorPtr->hi;
  180.                 else {
  181.                     accumulator[0].hi -= (divisorPtr->hi + 1);
  182.                 }
  183.                 accumulator[0].lo -= divisorPtr->lo;
  184.             }
  185.         }
  186.         *dividendPtr = accumulator[0];
  187. }
  188.